#pragma once
#ifndef CARD_H
#define CARD_H
/*
* The play cards for the game
*/

namespace SHGame {

	/*
	* The Playing Card ref class
	*/
	public ref class Card
	{
	public:
		static Card^ JackOfDiamonds = gcnew Card();
		/*
		* The suits of the playing cards
		*/
		static enum class Suit { Clubs, Spades, Hearts, Diamonds };

		/*
		* The face of the playing cards
		*/
		static enum class Face { Queen, Jack, Ace, Ten, King, Nine, Eight, Seven };

		
		
		static int findIndex(array<Face>^, Face);
		static int findIndex(array<Suit>^, Suit);

/*
		Order matters!
		*/
		static array<Suit>^ SUITS = {
			Suit::Clubs, Suit::Spades, Suit::Hearts, Suit::Diamonds 
		};

		/*
		Order matters!
		*/
		static array<Face>^ FACES = {
			Face::Queen, Face::Jack, Face::Ace, Face::Ten, Face::King, Face::Nine, Face::Eight, Face::Seven
		};

	private:
		/*
		this is a hard-coded rating for every card
		Used to see how good a hand is.
		this is dependent on the order of FACES and SUITS array
		the suit at index i = SUITS[i%4]
		*/
		static array<int>^ RATINGS = {
			// CLUBS SPADES HEARTS DIAMONDS
			924, 751, 650, 578, // Queens
			522, 476, 438, 404,  // Jacks
			50, 50, 50, 375, // Aces
			30, 30, 30, 349, // Tens
			10, 10, 10, 325, // kings
			5, 5, 5, 303, // nines
			4, 4, 4, 283, // Eights
			3, 3, 3, 264, // sevens
		};

	public:
		/*
		* This card's suit
		*/
		const Suit suit;
		/*
		* This card's face
		*/
		const Face face;
		/*
		* Constructs a new card with the given suit and face
		*/
		Card(Card::Suit s, Card::Face f) : suit (s), face (f) { };
		
		/*
		* Constructs a default card with arbitrary suit & face
		*/
		Card() : suit(Suit::Diamonds), face(Face::Jack)
		{ };
		/*
		* Returns the value of this card. 
		* The value is the "point value" in the game of Sheepshead.
		*/
		int getValue();

		/*
		* Returns the suit of this card
		*/
		Card::Suit getSuit();
		/*
		* Returns the face of this card
		*/
		Card::Face getFace();

		/*
		* Returns true if this card is "on suit" with the given card.
		* To be on suit, both cards must be of the same suit (i.e. spades or hearts).
		* All trump cards are only on suit with other trump cards; this method will
		* consider two cards onsuit if they are trump.
		*/
		bool onSuit(Card ^card);
		/*
		* Returns true if this card is "on suit" with the given suit.
		* To be on suit, this card must be of the same suit (i.e. spades or hearts).
		* This method does not take Trump into consideration. 
		*/
		bool onSuit(Card::Suit suit);

		/*
		* Returns true if this card is a trump card.
		* To be a trump card it must be a diamond, jack, or queen
		*/
		bool isTrump();

		virtual bool Equals(Card^);
	
		System::String^ toString();

		virtual System::String^ ToString() override {
			System::String^ str = face.ToString() + " of " + suit.ToString();
			return str;
		}

		int getRank();

		bool Takes(Card^);

		/*
		returns a rating of how good this card is for picking with.
		*/
		int GetPickRating();

		/*
		Returns the index in the power array
		*/
	private:
		int GetIndex();
	};
}

#endif